package com.yoyo.ad.tencent;

import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;

import com.qq.e.ads.banner2.UnifiedBannerADListener;
import com.qq.e.ads.banner2.UnifiedBannerView;
import com.qq.e.ads.cfg.VideoOption;
import com.qq.e.ads.interstitial2.UnifiedInterstitialAD;
import com.qq.e.ads.interstitial2.UnifiedInterstitialADListener;
import com.qq.e.ads.nativ.ADSize;
import com.qq.e.ads.nativ.NativeAD;
import com.qq.e.ads.nativ.NativeADDataRef;
import com.qq.e.ads.nativ.NativeADUnifiedListener;
import com.qq.e.ads.nativ.NativeExpressAD;
import com.qq.e.ads.nativ.NativeExpressADView;
import com.qq.e.ads.nativ.NativeUnifiedAD;
import com.qq.e.ads.nativ.NativeUnifiedADData;
import com.qq.e.comm.util.AdError;
import com.uber.autodispose.AutoDispose;
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider;
import com.yoyo.ad.api.YoYoConfig;
import com.yoyo.ad.confusion.AdManage;
import com.yoyo.ad.main.IAdBannerListener;
import com.yoyo.ad.main.IAdFactory_;
import com.yoyo.ad.main.IAdInteractionListener;
import com.yoyo.ad.main.IAdView;
import com.yoyo.ad.main.YoYoAd;
import com.yoyo.ad.utils.AnalysisUtils;

import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

public class TencentAdFactory implements IAdFactory_ {

    private IAdView mAdView;
    private IAdBannerListener mAdBannerListener;
    private IAdInteractionListener mAdInteractionListener;
    private Context mContext;

    private SparseArray<Long> adIds = new SparseArray<>();
    private SparseBooleanArray isIpReports = new SparseBooleanArray();
    private final int adType = AdManage.TENCENT;
    private UnifiedBannerView bv;
    private UnifiedInterstitialAD iad;
    private Disposable mDisposable;
    private boolean hasCallback;
    private int requestCode;
    private NativeExpressAD nativeExpressAD;
    private com.qq.e.ads.nativ.NativeUnifiedADData mNativeUnifiedADData;

    public TencentAdFactory(Context context) {
        mContext = context;
    }

    @Override
    public void setAdView(IAdView adView) {
        if (mAdView == null && adView != null)
            mAdView = adView;
    }


    @Override
    public void setAdBannerListener(IAdBannerListener adView) {
        if (mAdBannerListener == null && adView != null)
            mAdBannerListener = adView;
    }

    @Override
    public void setAdInteractionListener(IAdInteractionListener adInteractionListener) {
        if (mAdInteractionListener == null && adInteractionListener != null)
            mAdInteractionListener = adInteractionListener;
    }

    @Override
    public void setConfig(long adId, int adPositionId, boolean isIpReport) {
        adIds.put(adPositionId, adId);
        isIpReports.put(adPositionId, isIpReport);
    }

    private static final String TAG = "TencentAdFactory";

    @Override
    public void getYoyoAd(final int position, final int requestCode, int size, String adPlaceId, int type) {
//        SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocktFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        SSLSocketFactory.getSocketFactory().setHostnameVerifier(new AllowAllHostnameVerifier());
//        final long currentTimeMillis = System.currentTimeMillis();
//        Log.e(TAG, "start:" + currentTimeMillis);
        NativeAD mAdManager = new NativeAD(mContext, YoYoConfig.TENCENT_APP_ID, adPlaceId, new NativeAD.NativeAdListener() {
            @Override
            public void onADLoaded(List<NativeADDataRef> arg0) {
                AdManage.showAdSuccess(mContext, adType, adIds.get(position, 0L),
                        position, isIpReports.get(position, false));
                int size1 = arg0.size();
                List<YoYoAd> list = new ArrayList<>(size1);
                for (NativeADDataRef n : arg0) {
                    list.add(new TencentYoYoAd(n));
                }
                if (mAdView != null)
                    mAdView.adSuccess(requestCode, list);
//                Log.e(TAG, "end:" + System.currentTimeMillis());
//                Log.e(TAG, "differ:" + (currentTimeMillis - System.currentTimeMillis()));
            }

            @Override
            public void onADStatusChanged(NativeADDataRef nativeADDataRef) {

            }

            @Override
            public void onADError(NativeADDataRef nativeADDataRef, AdError adError) {
                noAd(adError, position, requestCode);
//                Log.e(TAG, "end:" + System.currentTimeMillis());
//                Log.e(TAG, "differ:" + (currentTimeMillis - System.currentTimeMillis()));
//                Log.e(TAG, "error:" + adError.getErrorCode()+"__"+adError.getErrorMsg());
            }

            @Override
            public void onNoAD(AdError adError) {
                noAd(adError, position, requestCode);
//                Log.e(TAG, "end:" + System.currentTimeMillis());
//                Log.e(TAG, "differ:" + (currentTimeMillis - System.currentTimeMillis()));
//                Log.e(TAG, "error:" + adError.getErrorCode()+"__"+adError.getErrorMsg());

            }
        });
        mAdManager.loadAD(size);
    }

    protected void noAd(AdError adError, int position, int requestCode) {
        AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_FAIL);
        mAdView.adFail(requestCode, adError.getErrorMsg());
        AdManage.showAdSuccess(mContext, adType, adIds.get(position, 0L),
                position, isIpReports.get(position, false));
    }

    @Override
    public void getExpressAd(final int position, final int requestCode, String adPlaceId, int size, int width) {
        if (!(mContext instanceof Activity)) {
            if (mAdView != null)
                mAdView.adFail(requestCode, "must in activity");
            return;
        }
        if (this.nativeExpressAD != null) {
            nativeExpressAD.loadAD(size);
            AdManage.showAdSuccess(mContext, adType, adIds.get(position, 0L),
                    position, isIpReports.get(position, false));
            return;
        }
        SSLSocketFactory.getSocketFactory().setHostnameVerifier(new AllowAllHostnameVerifier());
        nativeExpressAD = new NativeExpressAD(mContext, new ADSize(ADSize.FULL_WIDTH, ADSize.AUTO_HEIGHT), YoYoConfig.TENCENT_APP_ID, adPlaceId, new NativeExpressAD.NativeExpressADListener() {
            @Override
            public void onNoAD(AdError adError) {
                noAd(adError, position, requestCode);
            }

            @Override
            public void onADLoaded(List<NativeExpressADView> arg0) {
                AdManage.showAdSuccess(mContext, adType, adIds.get(position, 0L),
                        position, isIpReports.get(position, false));
                int size1 = arg0.size();
                List<YoYoAd> list = new ArrayList<>(size1);
                for (NativeExpressADView n : arg0) {
                    list.add(new TencentYoYoAd(n));
                }
                if (mAdView != null)
                    mAdView.adSuccess(requestCode, list);
            }

            @Override
            public void onRenderFail(NativeExpressADView nativeExpressADView) {
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_FAIL);
                mAdView.adFail(requestCode, "render fail");
            }

            @Override
            public void onRenderSuccess(NativeExpressADView nativeExpressADView) {
            }

            @Override
            public void onADExposure(NativeExpressADView nativeExpressADView) {
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_PRESENT);
            }

            @Override
            public void onADClicked(NativeExpressADView nativeExpressADView) {
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_CLICK);
            }

            @Override
            public void onADClosed(NativeExpressADView nativeExpressADView) {

            }

            @Override
            public void onADLeftApplication(NativeExpressADView nativeExpressADView) {

            }

            @Override
            public void onADOpenOverlay(NativeExpressADView nativeExpressADView) {

            }

            @Override
            public void onADCloseOverlay(NativeExpressADView nativeExpressADView) {

            }
        });
        nativeExpressAD.loadAD(size);
        AdManage.showAdSuccess(mContext, adType, adIds.get(position, 0L),
                position, isIpReports.get(position, false));
    }

    @Override
    public void getBanner(final int position, final int requestCode, String adPlaceId, ViewGroup adsParent, int width, int height) {
        if (!(mContext instanceof Activity)) {
            if (mAdBannerListener != null)
                mAdBannerListener.adFail(requestCode, "must in activity");
            return;
        }
        this.requestCode = requestCode;
//        autoClose();
        if (this.bv != null) {
            adsParent.removeView(bv);
            bv.loadAD();
            adsParent.addView(bv, getUnifiedBannerLayoutParams());
            return;
        }
        this.bv = new UnifiedBannerView(((Activity) mContext), YoYoConfig.TENCENT_APP_ID, adPlaceId, new UnifiedBannerADListener() {
            @Override
            public void onNoAD(AdError adError) {
                hasCallback = true;
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_FAIL);
                if (mAdBannerListener != null)
                    mAdBannerListener.adFail(requestCode, adError.getErrorMsg());
            }

            @Override
            public void onADReceive() {
                hasCallback = true;
            }

            @Override
            public void onADExposure() {
                hasCallback = true;
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_PRESENT);
                if (mAdBannerListener != null)
                    mAdBannerListener.adShow(requestCode);
            }

            @Override
            public void onADClosed() {
                if (mAdBannerListener != null)
                    mAdBannerListener.adDismissed(requestCode);
            }

            @Override
            public void onADClicked() {
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_CLICK);
                if (mAdBannerListener != null)
                    mAdBannerListener.adClick(requestCode);
            }

            @Override
            public void onADLeftApplication() {
                if (mAdBannerListener != null)
                    mAdBannerListener.adDismissed(requestCode);
            }

            @Override
            public void onADOpenOverlay() {

            }

            @Override
            public void onADCloseOverlay() {

            }
        });
        bv.loadAD();
        adsParent.addView(bv, getUnifiedBannerLayoutParams());
    }

    @Override
    public void getInteraction(final int position, final int requestCode, String adPlaceId) {
        if (!(mContext instanceof Activity)) {
            if (mAdInteractionListener != null)
                mAdInteractionListener.adFail(requestCode, "must in activity");
            return;
        }
        this.requestCode = requestCode;
//        autoClose();
        if (this.iad != null) {
//            iad.close();
//            iad.destroy();
//            iad = null;
            iad.loadAD();
            AdManage.showAdSuccess(mContext, adType, adIds.get(position, 0L),
                    position, isIpReports.get(position, false));
            return;
        }
        iad = new UnifiedInterstitialAD((Activity) mContext, YoYoConfig.TENCENT_APP_ID, adPlaceId, new UnifiedInterstitialADListener() {
            @Override
            public void onADReceive() {
                hasCallback = true;
                YoYoAd interactionAd = new TencentYoYoAd(iad);
                if (mAdInteractionListener != null)
                    mAdInteractionListener.adReady(requestCode, interactionAd);
            }

            @Override
            public void onNoAD(AdError adError) {
                hasCallback = true;
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_FAIL);
                if (mAdInteractionListener != null)
                    mAdInteractionListener.adFail(requestCode, adError.getErrorMsg());
            }

            @Override
            public void onADOpened() {
                hasCallback = true;
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_PRESENT);
                if (mAdInteractionListener != null)
                    mAdInteractionListener.adShow(requestCode);
            }

            @Override
            public void onADExposure() {
                hasCallback = true;
            }

            @Override
            public void onADClicked() {
                AnalysisUtils.addStatistics(adIds.get(position, 0L), AnalysisUtils.TYPE_CLICK);
                if (mAdInteractionListener != null)
                    mAdInteractionListener.adClick(requestCode);
            }

            @Override
            public void onADLeftApplication() {
                if (mAdInteractionListener != null)
                    mAdInteractionListener.adDismissed(requestCode);
            }

            @Override
            public void onADClosed() {
                if (mAdInteractionListener != null)
                    mAdInteractionListener.adDismissed(requestCode);
            }
        });
        //请求插屏广告，每次重新请求都可以调用此方法。
        iad.loadAD();
        AdManage.showAdSuccess(mContext, adType, adIds.get(position, 0L),
                position, isIpReports.get(position, false));
    }

    @Override
    public void onDestroy() {
        if (bv != null) {
            bv.destroy();
            bv = null;
        }
        if (iad != null) {
            iad.close();
            iad.destroy();
            iad = null;
        }
        if (nativeExpressAD != null) {
            nativeExpressAD = null;
        }
        if (mDisposable != null && !mDisposable.isDisposed()) {
            mDisposable.dispose();
            mDisposable = null;
        }
    }

    private void autoClose() {
        hasCallback = false;
        Observable<Long> longObservable = Observable.intervalRange(0, 5, 0, 1, TimeUnit.SECONDS) //起始值，发送总数量，初始延迟，固定延迟
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
        Consumer<Long> onNext = new Consumer<Long>() {
            @Override
            public void accept(Long aLong) {
                if (aLong > 3 && !hasCallback) {
                    if (mAdInteractionListener != null)
                        mAdInteractionListener.adFail(requestCode, "TimeOut");
                    onDestroy();
                }
            }
        };
        if (mContext instanceof LifecycleOwner) {
            mDisposable = longObservable
                    .as(AutoDispose.<Long>autoDisposable(AndroidLifecycleScopeProvider.from((LifecycleOwner) mContext, Lifecycle.Event.ON_DESTROY)))
                    .subscribe(onNext);
        } else {
            mDisposable = longObservable.subscribe(onNext);
        }
    }

    private FrameLayout.LayoutParams getUnifiedBannerLayoutParams() {
        Point screenSize = new Point();
        ((Activity) mContext).getWindowManager().getDefaultDisplay().getSize(screenSize);
        return new FrameLayout.LayoutParams(screenSize.x, Math.round(screenSize.x / 6.4F));
    }
}
